package jsu.blogger.controller;


import jakarta.servlet.http.HttpServletRequest;
import jsu.blogger.pojo.Result;
import jsu.blogger.service.inter.PostService;
import jsu.blogger.util.FileUtil;
import jsu.blogger.util.ReturnResultUtil;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.*;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("file")//post才可访问
public class FileController {
    private static final Logger logger = LoggerFactory.getLogger(FileController.class);

    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private PostService postService;
    @GetMapping("/{id}") // 处理 GET 请求，路径中包含 ID
    public Result getImgById(@PathVariable String id, @RequestParam(value = "type") String type, @RequestParam(value = "fileName",required = false) String fileName) {
        logger.info("Img请求的ID: {}, 类型: {}", id, type);
        // 根据类型判断是获取头像还是封面
        if ("avatar".equalsIgnoreCase(type)) {
            //有无头像
            Map<String, Object> profileImage = FileUtil.getImgAsBase64(FileUtil.PROFILE_PICTURE_DIR_NAME,id);
            if(profileImage .get("error")==null){
                return ReturnResultUtil.success(profileImage);
            }
        } else if ("cover".equalsIgnoreCase(type)) {
            // 处理获取封面的逻辑
            Map<String, Object>  coverImageResult = FileUtil.getImgAsBase64(FileUtil.POST_COVER_DIR_NAME,id);
            if(coverImageResult .get("error")==null){
                return ReturnResultUtil.success(coverImageResult);
            }
        }  else if ("tempPostCover".equalsIgnoreCase(type)) {
            // 处理获取封面的逻辑
            Map<String, Object>  coverImageResult = FileUtil.getImgAsBase64(FileUtil.TEMP_POST_COVER_DIR_NAME,id);
            if(coverImageResult .get("error")==null){
                return ReturnResultUtil.success(coverImageResult);
            }
        }
        else if ("tempPostImg".equals(type)) {
            String resourcePath=FileUtil.resourcePath+File.separator+FileUtil.TEMP_POST_IMG_DIR_NAME+File.separator+id+File.separator+fileName;
            logger.info("需要加载的图片路径是:"+resourcePath);
            Map<String, Object>  tempPostImgResult = FileUtil.getImgAsBase64ByPath(resourcePath);
            if(tempPostImgResult.get("error")==null){
                return ReturnResultUtil.success(tempPostImgResult);
            }
        } else if ("postImg".equals(type)) {
            String resourcePath = FileUtil.resourcePath + File.separator + FileUtil.POST_IMG_DIR_NAME + File.separator + id + File.separator + fileName;
            logger.info("需要加载的图片路径是:" + resourcePath);
            Map<String, Object> tempPostImgResult = FileUtil.getImgAsBase64ByPath(resourcePath);
            if (tempPostImgResult.get("error") == null) {
                return ReturnResultUtil.success(tempPostImgResult);
            }
        }
        else {
            // 如果类型不正确，返回错误信息
            return ReturnResultUtil.failure("无效的类型参数");
        }
        // 返回响应
        return ReturnResultUtil.failure("");
    }
    //文件上传
    @PostMapping("upload")
    public Result createBlog(
            @RequestParam("file") MultipartFile file,
            @RequestParam(value = "signId") String signId, // 获取 标识signId
            @RequestParam(value = "resourceId",required = false) Long resourceId,//联立的资源Id
            @RequestParam("userId") Long  userId, // userId 必须存在
            @RequestParam("type") String type, //必须存在
            @RequestParam("imageIndex") Long imageIndex,
            HttpServletRequest request) {
        logger.info("联立的资源Id"+resourceId);
        // 验证用户身份和文件标识
        String validationResult = validateUserAndFile(request, userId, signId, type);
        if (validationResult != null) {
            return ReturnResultUtil.failure(validationResult);
        }
        // 校验 imageIndex 是否为空且大于 0
        if (imageIndex == null || imageIndex <= 0) {
            return ReturnResultUtil.failure("imageIndex 必须大于 0");
        }
        // 检查是否是临时文件标识符
        if(!isTemporarySignIdValid(signId, userId)) {
            return ReturnResultUtil.failure("临时标识符验证失败");
        }
        Map<String,Object> objectMap=this.generateMapByType(type,signId);
        if(objectMap.get("resourcePath").equals("")){
            return ReturnResultUtil.failure("资源请求错误");
        }
        //处理文件 上锁 分布式锁   signId + type 锁对同用户和同一种资源进行上锁
        String lockKey = signId + ":" + type;  // 锁的唯一标识符 (signId + type)
        RLock lock = redissonClient.getLock(lockKey);
        try {
            if (lock.tryLock(10,30, TimeUnit.SECONDS)){
               String fileName=(boolean)objectMap.get("needNamed") ? signId:null;
                Map<String,String>  map=handleFileUpload(file, (String) objectMap.get("resourcePath"),fileName);
                map.put("imageIndex",String.valueOf(imageIndex));
              if(map.get("error")!=null){
                  return ReturnResultUtil.custom(0, map.get("error"), map);
              }else{
                  return ReturnResultUtil.success(map);
              }
            }
        }catch (Exception e){
            logger.error("处理文件异常");
            return ReturnResultUtil.failure("处理文件异常");
        }finally {
            lock.unlock();
        }
        //3.数据响应
        return ReturnResultUtil.failure("");
    }

    // 验证用户身份和文件标识的函数
    private String validateUserAndFile(HttpServletRequest request, Long userId, String signId, String type) {
        // 处理 userId，获取请求头中的 uid 并进行比较
        String uidHeader = request.getHeader("uid"); // 获取请求头中的 uid
        Long uidFromHeader = (uidHeader != null) ? Long.valueOf(uidHeader) : null;

        // 比较 userId 和 uid
        if (uidFromHeader == null || !uidFromHeader.equals(userId)) {
            return "用户身份验证失败";
        }

        // 验证文件标识 id 和文件上传类型
        if (signId == null || type == null) {
            return "文件标识和类型不能为空";
        }

        return null; // 如果验证通过，返回 null
    }

    // 处理文件上传的函数 怎么搞呢? file文件  资源存储地  文件名 默认资源包自增
    private Map<String,String> handleFileUpload(MultipartFile file, String storagePath,String storageFileName) {
        Map<String,String> map=new HashMap<>();
        // 检查文件是否为空
        if (file.isEmpty()) {
            map.put("error","上传的文件不能为空");
            return map;
        }
        // 获取文件名和扩展名
        String fileName = file.getOriginalFilename();
        String fileExtension = "";
        if (fileName != null && fileName.lastIndexOf(".") > 0) {
            fileExtension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
        }
        // 检查文件类型
        String contentType = file.getContentType();
        if (contentType.startsWith("image/")) {
            // 图片文件处理
            List<String> allowedImageExtensions = Arrays.asList("jpg", "jpeg", "png", "gif");
            if (!allowedImageExtensions.contains(fileExtension)) {
                map.put("error","只允许上传 JPG、JPEG、PNG 或 GIF 格式的图片");
                return map;
            }
        } else if (contentType.startsWith("text/")) {
            // 文本文件处理
            List<String> allowedTextExtensions = Arrays.asList("txt", "csv");
            if (!allowedTextExtensions.contains(fileExtension)) {
                map.put("error","只允许上传 TXT 或 CSV 格式的文本文件");
                return map;
            }
        } else if (contentType.startsWith("video/")) {
            // 视频文件处理
            List<String> allowedVideoExtensions = Arrays.asList("mp4", "avi", "mov");
            if (!allowedVideoExtensions.contains(fileExtension)) {
                map.put("error","只允许上传 MP4、AVI 或 MOV 格式的视频文件");
                return map;
            }
        } else {
            map.put("error", "不支持的文件类型");
            return map;
        }
        // 检查文件大小（例如：限制为 5MB）
        if (file.getSize() > 5 * 1024 * 1024) {
            map.put("error", "文件大小不能超过 5MB");
            return map;
        }

        // 存储文件到指定位置
        try {
            // 假设你有一个文件夹存储路径
            if(!FileUtil.createDirByPath(storagePath)){
                map.put("error", "文件夹创建失败");
                return map;
            }
            //如果为null 启用文件命名
            if(storageFileName==null) {
                //获取文件夹 最后文件的文件名   如果不存在则为1
                storageFileName = "1";
                File maxFile = FileUtil.getMaxValueFileInDirectory(storagePath);

                if (maxFile != null) {
                    storageFileName = String.valueOf(Integer.parseInt(Objects.requireNonNull(FileUtil.extractNumber(maxFile.getName()))) + 1);
                }
            }else{
                //根据文件包 删除文件名
                FileUtil.deleteFilesByPartialName(storagePath,storageFileName);
            }
            //文件存储地
            String storageAbsoluteDirPath =storagePath+File.separator+storageFileName + "." + fileExtension;
            File destinationFile = new File(storageAbsoluteDirPath);
            file.transferTo(destinationFile);
            //返回文件的存储路径或其他信息
            logger.info("文件上传成功: " + destinationFile.getAbsolutePath());
            map.put("frontFileName", fileName);
            map.put("storageFileName", storageFileName + "." + fileExtension);
           // map.put("signDir", uploadSignDir);

        } catch (Exception e) {
            logger.error("文件上传失败", e);
            map.put("error", "文件上传失败");
            return map;
        }

        return map; //  表示上传成功
    }



    private Map<String,Object> generateMapByType(String type,String signId) {
        Map<String,Object> resultMap=new HashMap<>();
        String resourcePath="";
        if("tempPostCover".equals(type)){
            resourcePath=FileUtil.createDirPath(FileUtil.TEMP_POST_COVER_DIR_NAME);
            resultMap.put("needNamed",true);
        } else if ("tempPostImg".equals(type)) {
            resourcePath=FileUtil.createDirPath(FileUtil.TEMP_POST_IMG_DIR_NAME)+File.separator+signId;
            resultMap.put("needNamed",false);
        }
        resultMap.put("resourcePath",resourcePath);
        return resultMap;
    }



    // 检查 signId 是否是个数字的函数
    private Long getNonTemporarySingId(String signId) {
        try {
            // 假设 postId 的第一个部分是非临时 ID
            return Long.parseLong(signId);
        } catch (NumberFormatException e) {
            logger.error("标识符转文字失败:" + signId);
            return null; // 如果转换失败，返回 null
        }
    }
    //验证临时标识符文件id
    private boolean isTemporarySignIdValid(String signId,Long userId) {
        // 验证临时 postId 中的下划线部分  时间戳_userId_随机值
        String[] postIdParts = signId.split("_");
        if (postIdParts.length < 3) {
            logger.error("临时 postId 格式不正确: " + signId);
            return false;
        }

        // 获取 postId 中的第二个数字
        String userIdFromPostId = postIdParts[1];
        if (!userIdFromPostId.equals(String.valueOf(userId))) {
            logger.error("postId 中的用户 ID 必须与提供的 userId 相同: " + signId);
            return false;
        }
        // 日志记录
        logger.info("临时标识符 验证成功 ---- 用户 userId: " + userId + ", signId: " + signId);
        return true;
    }

}
